/**
*
* @brief	开关控制服务
* @author	yun
* @date		2016-12-23
* @desc		(433模块控制卧室灯、台灯、厨房灯等设备)
* @version
*
*
*/

#include	"service_switch.h"

#include	"app_conf.h"
#include	"service_server.h"
#include	"cmsis_os.h"

#include	"platform_433module.h"
#include	"platform_logger.h"

#include	<string.h>
#include	<stdio.h>  

#define		len(arr)	(sizeof(arr)/sizeof(arr[0]))

#define		SWITCH_MSG_DATA_CLOSE		"close"
#define		SWITCH_MSG_DATA_OPEN		"open"

#define		SWITCH_MSG_TYPE_RESULT		"result"	// 操作结果
#define		SWITCH_MSG_TYPE_STATE		"state"		// 查询状态上报
#define		SWITCH_MSG_TYPE_HAND		"hand"		// 设备状态人手改变

#define		SWITCH_POST_TYPE_T			"type"
#define		SWITCH_POST_DATA_T			"data"

#define		SWITCH_MSG_FORMAT			"{\"type\":\"%s\",\"data\":\"%s\"}"		// 服务器通信格式
#define		SWITCH_DEV_FORMAT			"=%s,%s%d#"	// 433 厂商定义格式



// 设备与服务的对应信息
typedef struct {
	char 	* sev_id;        // 服务ID
	char 	* dev_id;        // 设备ID
	int 	dev_index;       // 开关的第几位
}sev_dev_t;


//
// 服务与设备ID对应信息
// 为了开发调试，先将服务ID应英文单词表示, 对于的设备直接写到程序里面
//
sev_dev_t sev_dev_arr[] = {
	{
		.sev_id = "bedroom-light-major",	// 卧室主灯
		.dev_id = "725000106",  
		.dev_index = 1
	},{
		.sev_id = "bedroom-light-minor",	// 卧室次灯
		.dev_id = "725000106",
		.dev_index = 2
	},{ 
		.sev_id = "kitchen-fan-extractor",	// 厨房 排气扇
		.dev_id = "725030371",
		.dev_index = 1
	},{
		.sev_id = "kitchen-light-major", 	// 厨房灯
		.dev_id = "725030371", 
		.dev_index = 2
	},{
		.sev_id = "bedroom-lamp-desk", 	// 我是台灯
		.dev_id = "810004835",
		.dev_index = 1
	}
};

//
// 433 设备查询列表
// 每个一段时间，查询列表中设备的状态
//
char * dev_query_arr[] = {
	"725000106",
	"725030371",
	"810004835"
};

//
// 操作系统相关变量定义
// 
static 	osThreadId		thread_switch_id = NULL;
static 	osMessageQId	switch_state_queue = NULL;
static 	osMessageQId	switch_operate_queue = NULL;

static void thread_switch(void const * argument);
static void thread_switch_query(void const * argument);

// 服务通信消息类型
typedef enum {
	SWITCH_EVENT_STATE = 0,		// 状态
	SWITCH_EVENT_OPERATE, 		// 操作
	SWITCH_EVENT_NONE,			// 无
}switch_queue_t;

// 
// 消息处理缓冲区
//
static char switch_msg_buffer[40];		// 消息发送缓冲区
static char switch_cmd_buffer[20];		// 向433设备发送指令
static char switch_st_buffer[20];		// 433 设备上返回的消息

// 开关设备的处理
static int switch_operate_handler(char * sev, char *op);
static int switch_state_handler(char * buffer);

static void switch_state_callback(char * buffer, int len);
static int switch_send_message(char * sev, char * data);

static int service_switch_callback(char *sev, cJSON * data);



//
// 设备操作
// sev: 服务的ID号
// op: 服务的操作
//
static int switch_operate_handler(char * sev, char *op){
	char switch_cmd[20];
	
    for(int i=0; i<len(sev_dev_arr); i++){
		if(strcmp(sev_dev_arr[i].sev_id, sev) == 0){
			// 找到对应的设备
			if(strcmp(op, SWITCH_MSG_DATA_OPEN) == 0){
				sprintf(switch_cmd, 
					SWITCH_DEV_FORMAT, sev_dev_arr[i].dev_id, "N", sev_dev_arr[i].dev_index);
			} else if (strcmp(op, SWITCH_MSG_DATA_CLOSE) == 0) {
				sprintf(switch_cmd, 
					SWITCH_DEV_FORMAT, sev_dev_arr[i].dev_id, "F", sev_dev_arr[i].dev_index);
			} else {
				return -1;
			}
			// 进行对应的操作
			vTaskSuspendAll();
			platform_module433_send((unsigned char *)switch_cmd, strlen(switch_cmd));
			xTaskResumeAll();
			return 0;
		}
	}
	return -1;
}

//
// 433设备上返回的消息解析
// 
static int switch_state_handler(char * buffer){
	log_debug_printf("433module: %s", buffer);
	
	char *dev = NULL;
	char *op = NULL;
	
	// 解析433设备报文
	if (buffer[0] != '=' || buffer[strlen(buffer) -1] != '#') {
		return -1;
	}
	buffer[strlen(buffer) -1] = '\0';
	op = strstr(buffer, ",");
	if (op == NULL) {
		return -1;
	}
	*op = '\0';
	op ++;
	dev = buffer + 1;
	
	char * state = NULL;
	char * type = NULL;
	int index = 0;

	
	// 控制命令返回结果
	if (op[0] == 'f' || op[0] == 'n') {
		type = SWITCH_MSG_TYPE_RESULT;
		index = op[1] - '0';
		state = op[0] == 'f' ? SWITCH_MSG_DATA_CLOSE :  SWITCH_MSG_DATA_OPEN;
		// 找到对于的服务
		for(int i=0; i<len(sev_dev_arr); i++){
			if(strcmp(sev_dev_arr[i].dev_id, dev) == 0 && sev_dev_arr[i].dev_index == index){
				sprintf(switch_msg_buffer, SWITCH_MSG_FORMAT, type, state);
				switch_send_message(sev_dev_arr[i].sev_id, switch_msg_buffer);
				log_info_printf("sev: %s  state: %s", sev_dev_arr[i].sev_id, state);
				return 0;
			}
		}
	}

	// 手动开启上报的结果
	if(op[0] == 'm'){
		type = SWITCH_MSG_TYPE_HAND;
		index = op[1] - '0';
		state = op[2] == '0' ? SWITCH_MSG_DATA_CLOSE : SWITCH_MSG_DATA_OPEN;
		// 找到对于的服务
		for(int i=0; i<len(sev_dev_arr); i++){
			if(strcmp(sev_dev_arr[i].dev_id, dev) == 0 && sev_dev_arr[i].dev_index == index){
				sprintf(switch_msg_buffer, SWITCH_MSG_FORMAT, type, state);
				switch_send_message(sev_dev_arr[i].sev_id, switch_msg_buffer);
				log_info_printf("sev: %s  state: %s", sev_dev_arr[i].sev_id, state);
				return 0;
			}
		}
	}
	
	// 查询命令返回的结果
	if(op[0] == 's'){
		index = op[1] - '0';
		type = SWITCH_MSG_TYPE_STATE;
		// 找到对于的服务
		for(int i = 0; i<len(sev_dev_arr); i++){
			if(strcmp(sev_dev_arr[i].dev_id, dev) == 0){
				// 处理对应的状态
				state = (index & (1 << (sev_dev_arr[i].dev_index - 1))) == 0 ? SWITCH_MSG_DATA_CLOSE : SWITCH_MSG_DATA_OPEN;				
				sprintf(switch_msg_buffer, SWITCH_MSG_FORMAT, type, state);
				switch_send_message(sev_dev_arr[i].sev_id, switch_msg_buffer);
				log_info_printf("sev: %s  state: %s", sev_dev_arr[i].sev_id, state);
			}
		}
	}
	return 0;
}

//
// 开关服务向服务器发送消息
// 如果设备处于未登陆状态，将状态信息本地存储
//
static int switch_send_message(char * sev, char * data){
	// 设备在线
	if(app_state == APP_SERVER_LOGIN){
		return server_send_data(sev, data);
	}
	
	// 设备离线
	
	return 0;
}

//
// 查询433设备的状态
// 将所有433设备的状态都查询一便
//
int switch_state_query(){
	// 创建线程
	osThreadDef(SwitchQuery, thread_switch_query, osPriorityAboveNormal, 0, 256);
	osThreadId thread_query_id = osThreadCreate(osThread(SwitchQuery), NULL);
	if(thread_query_id == NULL){
		log_error_printf("service: thread switch query crreate error");
		app_state_notification(APP_ERR);
		return -1;
	}
	return 0;
}

//
// 433设备状态信息查询线程
// 
static void thread_switch_query(void const * argument){
	log_debug_printf("thread: switch query");
	char switch_cmd[20];
	
	log_info_printf("switch: query");
	for(int i=0; i<len(dev_query_arr); i++){
		sprintf(switch_cmd, "=%s,%s#", dev_query_arr[i], "ST");
		platform_module433_send((unsigned char *)switch_cmd, strlen(switch_cmd));
		// 从发送查询指令，到接收到反馈大概需要260ms
		osDelay(305);
	}
	
	osThreadTerminate(NULL);
	while(1);
}

//
// 建立开关设备服务
// 
int service_switch_establish(void){
	// 创建通信消息队列
	switch_operate_queue = xQueueCreate(1, sizeof(switch_queue_t));
	if (switch_operate_queue == NULL) {
		log_error_printf("service: switch operate queue create error");
		app_state_notification(APP_ERR);
	}
	
	switch_state_queue = xQueueCreate(1, sizeof(switch_queue_t));
	if (switch_state_queue == NULL){
		log_error_printf("service: switch state queue create error");
		app_state_notification(APP_ERR);
	}
	
	// 创建线程
	osThreadDef(Switch, thread_switch, osPriorityNormal, 0, 256);
	thread_switch_id = osThreadCreate(osThread(Switch), NULL);
	if(thread_switch_id == NULL){
		log_error_printf("service: thread switch create error");
		app_state_notification(APP_ERR);
		return -1;
	}
	
	// 监听服务器上消息推送
	for(int i=0; i<len(sev_dev_arr); i++){
		server_post_subscribe(sev_dev_arr[i].sev_id, service_switch_callback);
	}
		
	return 0;
}


//
// 销毁开关设备服务
//
int service_switch_destroy(void){
	if(thread_switch_id != NULL){
		osThreadTerminate(thread_switch_id);
		thread_switch_id = NULL;
	}
	
	if(switch_operate_queue != NULL){
		vQueueDelete(switch_operate_queue);
		switch_operate_queue = NULL;
	}
	
	if(switch_state_queue != NULL){
		vQueueDelete(switch_state_queue);
		switch_state_queue = NULL;
	}
	
	return 0;
}


//
// 开关服务线程
//
static void thread_switch(void const * argument){
	log_notice_printf("thread: switch");
	
	platform_module433_init();
	platform_module433_notification(switch_state_callback);
	
	log_notice_printf("timeout");
	
	osEvent switch_event;
	while(1){
		switch_event = osMessageGet(switch_state_queue, SEV_SWITCH_QUERY_INTERVAL);
		// 超时事件
		if(switch_event.status == osEventTimeout){
			switch_state_query();
			continue;
		}
		
		// 消息事件
		if(switch_event.status == osEventMessage) {
			switch(switch_event.value.v) {
				case SWITCH_EVENT_OPERATE:
					break;
				
				case SWITCH_EVENT_STATE:
					switch_state_handler(switch_st_buffer);
					break;
				
				default:
					break;
			}
		}
	}
}

//
// 433设备消息接收回掉函数
//
static void switch_state_callback(char * buffer, int len){
	memcpy(switch_st_buffer, buffer, len);
	if(switch_state_queue != NULL){
		switch_queue_t event = SWITCH_EVENT_STATE;
		osMessagePut(switch_state_queue, event, 100);
	}
	return;
}


//
// 服务器推送的开关服务控制信息
// sev: 服务ID
// data: json格式数据
//
static int service_switch_callback(char *sev, cJSON * data){
	if (data == NULL){
		return -1;
	}
	
	// type
	cJSON * type = cJSON_GetObjectItem(data, SWITCH_POST_TYPE_T);
	if (type == NULL || type->type != cJSON_String) {
		return -1;
	}
	
	// data 
	cJSON * operate = cJSON_GetObjectItem(data, SWITCH_POST_DATA_T);
	if (operate == NULL || operate->type != cJSON_String) {
		return -1;
	}
	
	// 处理
	return switch_operate_handler(sev, operate->valuestring);
}

//
// 开关服务接收外界的命令行控制
//  	查询 switch:query
//		控制 switch:服务ID,open or close
//
int switch_operate_cmd(char *cmd){
	
	// 设备状态查询
	if(strcmp(cmd, "query") == 0){
		switch_state_query();
		return 0;
	}
	
	// 开关设备控制
	char * sev = cmd;
	char * op = strstr(cmd, ",");
	if (op == NULL) {
		return -1;
	}
	
	*op = '\0';
	op ++;
	return switch_operate_handler(sev, op);
}


/**

开关服务测试

1、控制测试(通过命令行实现)

	格式: switch:sev id,open or close  
	例如：switch:bedroom-lamp-desk,close

2、手动开关设备状态信息返回
	
	开启服务，直接测试

3、查询设备状态(命令行实现)

	格式: switch:query

**/





















